package com.ruoyi.learn.java.collection;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConcurrentHashMapExample {
    // 创建 ConcurrentHashMap 实例
    private static final ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
    // 用于等待所有线程完成
    private static final CountDownLatch latch = new CountDownLatch(4);

    public static void main(String[] args) throws InterruptedException {
        // 初始化数据
        concurrentMap.put("A", 100);
        concurrentMap.put("B", 200);
        concurrentMap.put("C", 300);
        concurrentMap.put("D", 400);

        System.out.println("初始映射: " + concurrentMap);

        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(4);

        // 提交四个不同的任务
        executor.submit(new AddTask("E", 500));
        executor.submit(new UpdateTask("A", 50));
        executor.submit(new RemoveTask("B"));
        executor.submit(new ReadTask());

        // 等待所有任务完成
        latch.await();
        executor.shutdown();

        System.out.println("\n最终映射状态: " + concurrentMap);
    }

    // 添加元素的任务
    static class AddTask implements Runnable {
        private final String key;
        private final Integer value;

        AddTask(String key, Integer value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public void run() {
            try {
                // putIfAbsent: 仅当key不存在时才添加
                Integer previousValue = concurrentMap.putIfAbsent(key, value);
                if (previousValue == null) {
                    System.out.println(Thread.currentThread().getName() +
                            " 添加了新元素: " + key + " = " + value);
                } else {
                    System.out.println(Thread.currentThread().getName() +
                            " 元素 " + key + " 已存在，值为: " + previousValue);
                }
            } finally {
                latch.countDown();
            }
        }
    }

    // 更新元素的任务
    static class UpdateTask implements Runnable {
        private final String key;
        private final Integer delta;

        UpdateTask(String key, Integer delta) {
            this.key = key;
            this.delta = delta;
        }

        @Override
        public void run() {
            try {
                // 原子更新: 增加指定值
                concurrentMap.computeIfPresent(key, (k, v) -> v + delta);
                System.out.println(Thread.currentThread().getName() +
                        " 更新后 " + key + " 的值为: " + concurrentMap.get(key));
            } finally {
                latch.countDown();
            }
        }
    }

    // 移除元素的任务
    static class RemoveTask implements Runnable {
        private final String key;

        RemoveTask(String key) {
            this.key = key;
        }

        @Override
        public void run() {
            try {
                // 原子移除: 仅当值匹配时才移除
                boolean removed = concurrentMap.remove(key, concurrentMap.get(key));
                if (removed) {
                    System.out.println(Thread.currentThread().getName() +
                            " 成功移除元素: " + key);
                } else {
                    System.out.println(Thread.currentThread().getName() +
                            " 移除元素 " + key + " 失败");
                }
            } finally {
                latch.countDown();
            }
        }
    }

    // 读取元素的任务
    static class ReadTask implements Runnable {
        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " 开始读取元素");

                // 遍历键集
                Set<String> keys = concurrentMap.keySet();
                for (String key : keys) {
                    System.out.println(Thread.currentThread().getName() +
                            " 读取到: " + key + " = " + concurrentMap.get(key));
                    // 模拟处理时间
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                latch.countDown();
            }
        }
    }
}

